InversifyJSをシンプルに使ってみる
InversifyJSはおそらくJS/TSで一番使われているDIコンテナライブラリだと思います。
こちら、かなり機能が多いのですが、
- toConstantValue()
- toDynamicValue()
- toDynamicValue().inSingleScope()
を押さえて使い分ければ大体のユースケースに対応できるのでは?という気がしたので紹介します。
なお、個人的な好みによりDecoratorは使わない方向とします。
環境
- node 16.14.0
- inversify 6.0.1
toConstantValue()
toConstantValue()は一番シンプルに値を登録する方法です。
import { Container } from 'inversify' const container = new Container() container.bind('CONSTANT').toConstantValue('Something') const gotValue = container.get('CONSTANT') console.log(gotValue) // => 'Something' を出力
'CONSTANT'
というキーに 'Something'
という文字列の値を登録して取得する例です。メソッドの名前の通り定数をセットするような感じです。
toDynamicValue()
toDynamicValue()は値を返す関数を登録します。登録した関数は値を取得する際に実行されるため、遅延評価の登録方法といえそうです。
import { Container } from 'inversify' const container = new Container() container.bind('DYNAMIC').toDynamicValue(() => { return 'Something' }) const gotValue = container.get('DYNAMIC') console.log(gotValue) // => 'Something' を出力
また、toDynamicValue()は他の登録値を取得して値を返すといったことができます。引数の context
に container
プロパティがあるので、そこから get()
メソッドを使用することができます。
container.bind('DYNAMIC_1').toDynamicValue(() => { return 'Something' }) container.bind('DYNAMIC_2').toDynamicValue((context) => { return context.container.get('DYNAMIC_1') })
このようにDYNAMIC_1に依存するDYNAMIC_2の値を解決することができます。
そして、toDynamicValue()は取得される度に関数が実行されます。次に例を示します。
container.bind('DYNAMIC').toDynamicValue(() => { console.log('Run toDynamicValue callback') // デバッグのために追加 return 'Something' }) const gotValue = container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力 console.log(gotValue) // => 'Something' を出力 container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力 container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力
デバッグのために関数内に console.log('Run toDynamicValue callback')
を仕込みました。この状態で container.get('DYNAMIC')
を3度行うと 'Run toDynamicValue callback'
が3行出力されます。つまり3回関数が実行されています。
この点、1度目の取得で値をキャッシュして、2度目の取得以降はキャッシュ値を返したいニーズもあると思います。そのような場合は次に紹介するtoDynamicValue().inSingleScope()が使えます。
toDynamicValue().inSingleScope()
上のサンプルにinSingletonScope()を追加したコードが下記です。
import { Container } from 'inversify' const container = new Container() container .bind('DYNAMIC') .toDynamicValue(() => { console.log('Run toDynamicValue callback') return 'Something' }) .inSingletonScope() // 追加 const gotValue = container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力 console.log(gotValue) // => 'Something' を出力 container.get('DYNAMIC') // => 出力なし container.get('DYNAMIC') // => 出力なし
このようにしてあげると、2度目の取得以降は 'Run toDynamicValue callback'
を出力しないため、関数が一度しか実行されていないことがわかります。
まとめ
3つのAPIを紹介しましたが、この中でも特に toDynamicValue().inSingleScope()
を多用すれば
- 不要なインスタンス生成を減らせる
- 2度目の取得以降はキャッシュを返す
という点からパフォーマンス面で良いのではないかと思いました。
参考になれば幸いです。